0%

删库跑路之前该做的事情

最近两年老是听到有程序员跑路之前删库的笑话
小公司对数据库的权限管理缺失不太严谨
我在为CDH集群实现Kerberos的时候还是挺有感触的
权限控制应该是属于运维的相对高级的内容

权限控制姑且按下不表,这边记录一下rm -rf 失误之后的数据恢复

1.救命稻草–ext3grep

下载ext3grep,安装(编译安装过程艰辛暂且不表)。

先执行扫描文件名命令:

1
ext3grep /dev/vgdata/LogVol00 --dump-names

这款软件不能按目录恢复文件,只能执行恢复全部命令:

1
ext3grep /dev/vgdata/LogVol00 --restore-all

结果当前盘空间不足,没办法只能恢复文件,尝试了几个文件,居然部分成功部分失败

1
ext3grep /dev/vgdata/LogVol00 --restore-file var/lib/mysql/aqsh/tb_b_attench.MYD

将所有文件名重定向到一个文件文件中

1
ext3grep /dev/vgdata/LogVol00 --dump-names >/usr/allnames.txt

编写脚本恢复文件:

1
2
3
4
5
6
7
8
9
10
while read LINE
do
echo "begin to restore file " $LINE
ext3grep /dev/vgdata/LogVol00 --restore-file $LINE
if [ $? != 0 ]
then
echo "restore failed, exit"
# exit 1
fi
done < ./mysqltbname.txt

数据没有被完全恢复!

2.换一款软件试试 extundelete

这款软甲您可以按照目录恢复

1
extundelete /dev/vgdata/LogVol00 --restore-directory var/lib/mysql/aqsh

还是不行

3.换个思路 binlog

服务器开启binlog的情况下,可以通过binlong恢复

于是从dump出来的文件名里找到binlog的文件,一共三个,mysql-binlog0001,mysql-bin.000009,mysql-bin.000010,恢复一下0001

1
ext3grep /dev/vgdata/LogVol00 --restore-file var/lib/mysql/mysql-bin.000001

恢复失败

换一个文件

mysql-bin.000010大概几百MB,应该靠谱一点,恢复成功!

恢复命令:

1
mysqlbinlog /usr/mysql-bin.000010 | mysql -uroot -p

数据回来了

恢复失败的两款软件:

1
2
3
4
5
6
7
8
9
10
11
12
13
本文所用到的工具链接:

1.ext3grep:https://code.google.com/p/ext3grep/

编译安装依赖包比较多,可以到网上搜索如何安装。可惜的是作者给出的howto被墙了,我FQ将how to 的pdf文档下载下来了,读完后你将会对linux的文件系统有进一步的认识。下载howto。


这个工具有一个bug,出错后不会向下执行ext3grep: init_directories.cc:534: void init_directories(): Assertion `lost_plus_found_directory_iter != all_directories.end()' failed.,从而造成恢复失败,作者放出了一个补丁,下载地址:补丁下载。不明白为什么作者新版没有把这个补丁加进去。


2.extundelete:http://extundelete.sourceforge.net/

功能跟ext3grep差不多,原理应该也差不多。只是号称可以还原目录,我这里没有试验成功。

4.如果数据库被rm命令删除了,主进程还没有退出的恢复办法

1.模拟删库(包含数据文件,控制文件,联机日志文件)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
sys@GLOBAL>col NAME for a100;
sys@GLOBAL>select FILE#,NAME from v$datafile;
FILE# NAME
---------- ----------------------------------------------------------------------------------------------------
1 /home/oracle/app/oradata/global/system01.dbf
2 /home/oracle/app/oradata/global/sysaux01.dbf
3 /home/oracle/app/oradata/global/undotbs01.dbf
4 /home/oracle/app/oradata/global/users01.dbf
5 /home/oracle/app/oradata/global/GLOBAL_ORDER01.dbf
6 /home/oracle/app/oradata/global/TS_DCIS_WMS01.dbf
7 /home/oracle/app/oradata/global/TS_DCIS_WMS02.dbf
7 rows selected.
sys@GLOBAL>!rm -f /home/oracle/app/oradata/global/*
sys@GLOBAL>create table t tablespace users as select * from dual;
create table t tablespace users as select * from dual
*
ERROR at line 1:
ORA-01116: error in opening database file 4
ORA-01110: data file 4: '/home/oracle/app/oradata/global/users01.dbf'
ORA-27041: unable to open file
Linux-x86_64 Error: 2: No such file or directory
Additional information: 3

数据库文件和控制文件以及联机日志文件都已经被删了,尝试创建一个表时oracle报打不开数据文件异常。

2.检查 lgwr 的进程 PID

1
2
[oracle@ol6-a ~]$ ps -ef | grep lgwr | grep -v grep
oracle 3804 1 0 Dec02 ? 00:01:40 ora_lgwr_global

3.lgwr 会打开所有数据文件、联机日志文件、控制文件的句柄。在 proc 目录中可以查到,目录名是进程 PID,fd 表示文件描述符。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[oracle@ol6-a ~]$ cd /proc/3804/fd
[oracle@ol6-a fd]$ ls -l
total 0
lr-x------. 1 oracle oinstall 64 Dec 7 03:49 0 -> /dev/null
l-wx------. 1 oracle oinstall 64 Dec 7 03:49 1 -> /dev/null
lrwx------. 1 oracle oinstall 64 Dec 7 03:49 10 -> /home/oracle/app/product/11.2.0/db_1/dbs/lkGLOBAL
lr-x------. 1 oracle oinstall 64 Dec 7 03:49 13 -> /home/oracle/app/product/11.2.0/db_1/rdbms/mesg/oraus.msb
l-wx------. 1 oracle oinstall 64 Dec 7 03:49 2 -> /dev/null
lrwx------. 1 oracle oinstall 64 Dec 7 03:49 256 -> /home/oracle/app/oradata/global/control01.ctl (deleted)
lrwx------. 1 oracle oinstall 64 Dec 7 03:49 257 -> /home/oracle/app/fast_recovery_area/global/control02.ctl
lrwx------. 1 oracle oinstall 64 Dec 7 03:49 258 -> /home/oracle/app/oradata/global/redo01.log (deleted)
lrwx------. 1 oracle oinstall 64 Dec 7 03:49 259 -> /home/oracle/app/oradata/global/redo02.log (deleted)
lrwx------. 1 oracle oinstall 64 Dec 7 03:49 260 -> /home/oracle/app/oradata/global/redo03.log (deleted)
lrwx------. 1 oracle oinstall 64 Dec 7 03:49 261 -> /home/oracle/app/oradata/global/system01.dbf (deleted)
lrwx------. 1 oracle oinstall 64 Dec 7 03:49 262 -> /home/oracle/app/oradata/global/sysaux01.dbf (deleted)
lrwx------. 1 oracle oinstall 64 Dec 7 03:49 263 -> /home/oracle/app/oradata/global/undotbs01.dbf (deleted)
lrwx------. 1 oracle oinstall 64 Dec 7 03:49 264 -> /home/oracle/app/oradata/global/users01.dbf (deleted)
lrwx------. 1 oracle oinstall 64 Dec 7 03:49 265 -> /home/oracle/app/oradata/global/GLOBAL_ORDER01.dbf (deleted)
lrwx------. 1 oracle oinstall 64 Dec 7 03:49 266 -> /home/oracle/app/oradata/global/TS_DCIS_WMS01.dbf (deleted)
lrwx------. 1 oracle oinstall 64 Dec 7 03:49 267 -> /home/oracle/app/oradata/global/TS_DCIS_WMS02.dbf (deleted)
lrwx------. 1 oracle oinstall 64 Dec 7 03:49 268 -> /home/oracle/app/oradata/global/temp01.dbf (deleted)
lr-x------. 1 oracle oinstall 64 Dec 7 03:49 3 -> /dev/null
lr-x------. 1 oracle oinstall 64 Dec 7 03:49 4 -> /dev/null
lr-x------. 1 oracle oinstall 64 Dec 7 03:49 5 -> /dev/null
lr-x------. 1 oracle oinstall 64 Dec 7 03:49 6 -> /home/oracle/app/product/11.2.0/db_1/rdbms/mesg/oraus.msb
lr-x------. 1 oracle oinstall 64 Dec 7 03:49 7 -> /proc/3804/fd
lr-x------. 1 oracle oinstall 64 Dec 7 03:49 8 -> /dev/zero
lrwx------. 1 oracle oinstall 64 Dec 7 03:49 9 -> /home/oracle/app/product/11.2.0/db_1/dbs/hc_global.dat

4.直接 cp 这些句柄文件名回原位置。

1
2
3
4
5
6
7
8
9
10
11
12
[oracle@ol6-a fd]$ cp 256 /home/oracle/app/oradata/global/control01.ctl
[oracle@ol6-a fd]$ cp 258 /home/oracle/app/oradata/global/redo01.log
[oracle@ol6-a fd]$ cp 259 /home/oracle/app/oradata/global/redo02.log
[oracle@ol6-a fd]$ cp 260 /home/oracle/app/oradata/global/redo03.log
[oracle@ol6-a fd]$ cp 261 /home/oracle/app/oradata/global/system01.dbf
[oracle@ol6-a fd]$ cp 262 /home/oracle/app/oradata/global/sysaux01.dbf
[oracle@ol6-a fd]$ cp 263 /home/oracle/app/oradata/global/undotbs01.dbf
[oracle@ol6-a fd]$ cp 264 /home/oracle/app/oradata/global/users01.dbf
[oracle@ol6-a fd]$ cp 265 /home/oracle/app/oradata/global/GLOBAL_ORDER01.dbf
[oracle@ol6-a fd]$ cp 266 /home/oracle/app/oradata/global/TS_DCIS_WMS01.dbf
[oracle@ol6-a fd]$ cp 267 /home/oracle/app/oradata/global/TS_DCIS_WMS02.dbf
[oracle@ol6-a fd]$ cp 268 /home/oracle/app/oradata/global/temp01.dbf

5.检查数据库是否可用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[oracle@ol6-a fd]$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.4.0 Production on Wed Dec 7 03:47:39 2016

Copyright (c) 1982, 2013, Oracle. All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, Oracle Label Security, OLAP, Data Mining
and Real Application Testing options

sys@GLOBAL>create table t tablespace users as select * from dual;

Table created.

完成数据文件恢复。

6.如果数据库不可用,可能还会涉及到数据文件等的恢复过程,使用以下命令恢复数据文件:

1
2
3
alter database datafile 1 offline;
recover datafile 1;
alter database datafile 1 online;

恢复的原理:在 Linux 操作系统中,如果文件从操作系统级别被rm掉,之前打开该文件的进程仍然持有相应的文件句柄,所指向的文件仍然可以读写,并且该文件的文件描述符可以从 /proc 目录中获得。但是要注意的是,此时如果关闭数据库,则此句柄会消失,那么除了扫描磁盘进行文件恢复之外就没有其它方法了,因此在数据库出现问题的时候,如果不确认情况的复杂程度,千万不要随便关闭数据库。重启数据库往往是没有意义的,甚至是致命的。

如果不慎关闭数据库,句柄丢失,还可以通过恢复工具来恢复数据库文件(只要数据在磁盘上还没有被覆盖,且有足够的磁盘空间存放待恢复的文件),可以使用的工具有testdisk和extundelete。

以testdisk恢复文件为例,使用testdisk的Filesystem Utils工具将被误删的文件恢复到指定目录:

1.选择误删文件所在介质

2.使用Filesystem Utils工具

3.选择需要恢复的文件并恢复到指定目录:


这边顺便记录一下今天遇到的Bayes问题,很奇怪的问题

三个盒子,每个盒子两个球,一个全是红球,一个全是蓝球,一个里面混杂。

问题就是在拿到一个红球的情况下,第二个球还是红球的几率是多大。

答案是三分之二!

延伸开来还可以涉及到一个大数定理。

看完之后感觉自己学的概率论是不是白学了。